package com.kexio.security.service.impl;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.kexio.common.dto.PageRequest;
import com.kexio.common.dto.PageResponse;
import com.kexio.security.domain.Permission;
import com.kexio.security.domain.enums.PermissionStatus;
import com.kexio.security.service.PermissionRepository;
import com.kexio.security.service.PermissionService;

/**
 * 权限业务服务实现类
 * 
 * @author kexio
 */
@Service
@Transactional(readOnly = true)
public class PermissionServiceImpl implements PermissionService {

    private static final Logger log = LoggerFactory.getLogger(PermissionServiceImpl.class);

    private final PermissionRepository permissionRepository;

    public PermissionServiceImpl(PermissionRepository permissionRepository) {
        this.permissionRepository = permissionRepository;
    }

    @Override
    @Transactional
    public Permission createPermission(Permission permission) {
        log.info("开始创建权限: {}", permission.getPermissionName());
        
        // 验证权限编码唯一性
        if (existsByPermissionCode(permission.getPermissionCode(), null)) {
            throw new RuntimeException("权限编码已存在");
        }
        
        // 验证权限名称唯一性
        if (existsByPermissionName(permission.getPermissionName(), null)) {
            throw new RuntimeException("权限名称已存在");
        }

        // 设置默认值
        if (permission.getStatus() == null) {
            permission.setStatus(PermissionStatus.ENABLED.getCode());
        }
        if (permission.getParentId() == null) {
            permission.setParentId(0L);
        }
        if (permission.getSortOrder() == null) {
            permission.setSortOrder(0);
        }

        permission = permissionRepository.save(permission);
        log.info("权限创建成功: {} (ID: {})", permission.getPermissionName(), permission.getId());
        return permission;
    }

    @Override
    @Transactional
    public Permission updatePermission(Permission permission) {
        log.info("开始更新权限: {}", permission.getId());
        
        Permission existingPermission = permissionRepository.findById(permission.getId())
                .orElseThrow(() -> new RuntimeException("权限不存在"));

        // 验证权限编码唯一性（排除当前权限）
        if (!permission.getPermissionCode().equals(existingPermission.getPermissionCode())) {
            if (existsByPermissionCode(permission.getPermissionCode(), permission.getId())) {
                throw new RuntimeException("权限编码已存在");
            }
        }

        // 验证权限名称唯一性（排除当前权限）
        if (!permission.getPermissionName().equals(existingPermission.getPermissionName())) {
            if (existsByPermissionName(permission.getPermissionName(), permission.getId())) {
                throw new RuntimeException("权限名称已存在");
            }
        }

        permission = permissionRepository.save(permission);
        log.info("权限更新成功: {} (ID: {})", permission.getPermissionName(), permission.getId());
        return permission;
    }

    @Override
    public Permission getPermissionById(Long id) {
        return permissionRepository.findById(id).orElse(null);
    }

    @Override
    public Permission getPermissionByCode(String permissionCode) {
        return permissionRepository.findByPermissionCode(permissionCode).orElse(null);
    }

    @Override
    public PageResponse<Permission> queryPermissions(String permissionName, Integer permissionType, Integer status, PageRequest pageRequest) {
        return permissionRepository.findPage(permissionName, permissionType, status, pageRequest);
    }

    @Override
    public List<Permission> getAllPermissions() {
        return permissionRepository.findAll();
    }

    @Override
    public List<Permission> getPermissionTree() {
        List<Permission> allPermissions = getAllPermissions();
        return buildPermissionTree(allPermissions);
    }

    @Override
    public List<Permission> getPermissionsByStatus(Integer status) {
        return permissionRepository.findByStatus(status);
    }

    @Override
    public List<Permission> getPermissionsByType(Integer permissionType) {
        return permissionRepository.findByPermissionType(permissionType);
    }

    @Override
    public List<Permission> getPermissionsByParentId(Long parentId) {
        return permissionRepository.findByParentId(parentId);
    }

    @Override
    public List<Permission> getPermissionsByUserId(Long userId) {
        return permissionRepository.findByUserId(userId);
    }

    @Override
    public List<Permission> getPermissionsByRoleId(Long roleId) {
        return permissionRepository.findByRoleId(roleId);
    }

    @Override
    @Transactional
    public boolean enablePermission(Long id) {
        return updatePermissionStatus(id, PermissionStatus.ENABLED.getCode());
    }

    @Override
    @Transactional
    public boolean disablePermission(Long id) {
        return updatePermissionStatus(id, PermissionStatus.DISABLED.getCode());
    }

    private boolean updatePermissionStatus(Long id, Integer status) {
        Permission permission = permissionRepository.findById(id).orElse(null);
        if (permission == null) {
            return false;
        }
        
        permission.setStatus(status);
        permission.setUpdatedTime(LocalDateTime.now());
        permissionRepository.save(permission);
        return true;
    }

    @Override
    @Transactional
    public boolean deletePermission(Long id) {
        // 检查是否有子权限
        List<Permission> children = getPermissionsByParentId(id);
        if (!children.isEmpty()) {
            throw new RuntimeException("存在子权限，无法删除");
        }
        
        int rows = permissionRepository.deleteById(id);
        return rows > 0;
    }

    @Override
    @Transactional
    public int deletePermissions(List<Long> ids) {
        if (ids == null || ids.isEmpty()) {
            return 0;
        }
        
        // 检查是否有子权限
        for (Long id : ids) {
            List<Permission> children = getPermissionsByParentId(id);
            if (!children.isEmpty()) {
                throw new RuntimeException("权限ID " + id + " 存在子权限，无法删除");
            }
        }
        
        return permissionRepository.deleteByIds(ids);
    }

    @Override
    public boolean existsByPermissionCode(String permissionCode, Long excludeId) {
        return permissionRepository.existsByPermissionCode(permissionCode, excludeId);
    }

    @Override
    public boolean existsByPermissionName(String permissionName, Long excludeId) {
        return permissionRepository.existsByPermissionName(permissionName, excludeId);
    }

    @Override
    public List<Permission> buildPermissionTree(List<Permission> permissions) {
        if (permissions == null || permissions.isEmpty()) {
            return new ArrayList<>();
        }
        
        // 按父子关系构建树形结构
        List<Permission> rootPermissions = new ArrayList<>();
        
        for (Permission permission : permissions) {
            if (permission.getParentId() == null || permission.getParentId() == 0) {
                // 根权限
                rootPermissions.add(permission);
                buildChildren(permission, permissions);
            }
        }
        
        // 按排序号排序
        rootPermissions.sort((a, b) -> {
            if (a.getSortOrder() == null) a.setSortOrder(0);
            if (b.getSortOrder() == null) b.setSortOrder(0);
            return a.getSortOrder().compareTo(b.getSortOrder());
        });
        
        return rootPermissions;
    }

    private void buildChildren(Permission parent, List<Permission> allPermissions) {
        List<Permission> children = allPermissions.stream()
                .filter(p -> parent.getId().equals(p.getParentId()))
                .sorted((a, b) -> {
                    if (a.getSortOrder() == null) a.setSortOrder(0);
                    if (b.getSortOrder() == null) b.setSortOrder(0);
                    return a.getSortOrder().compareTo(b.getSortOrder());
                })
                .collect(Collectors.toList());
                
        parent.setChildren(children);
        
        for (Permission child : children) {
            buildChildren(child, allPermissions);
        }
    }

    @Override
    public Set<String> getUserPermissionCodes(Long userId) {
        List<Permission> permissions = getPermissionsByUserId(userId);
        return permissions.stream()
                .map(Permission::getPermissionCode)
                .collect(Collectors.toSet());
    }

    @Override
    public boolean hasPermission(Long userId, String permissionCode) {
        Set<String> userPermissions = getUserPermissionCodes(userId);
        return userPermissions.contains(permissionCode);
    }
}
